package com.dyt.itool.util;

import org.apache.log4j.Logger;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class ByteBuffer {

	private static final Logger logger = Logger.getLogger( ByteBuffer.class );

	private ByteBuf buffer;

	public ByteBuffer( ){
		this.buffer = Unpooled.buffer( );
	}
	
	public ByteBuffer( ByteBuf buffer ){
		this.buffer = buffer;
	}
	
	public ByteBuffer( byte[] bytes ){
		this.buffer =  Unpooled.buffer( );
		buffer.writeBytes( bytes );
	}
	
	public byte[] array(){
		return buffer.array();
	}
	
	public boolean readBool(){
		return buffer.readBoolean();
	}

	public byte readByte(){
		return buffer.readByte();
	}

	public short readShort(){
		return buffer.readShort();
	}

	public int readInt(){
		return buffer.readInt();
	}

	public long readLong(){
		return buffer.readLong();
	}

	public float readFloat(){
		return buffer.readFloat();
	}

	public double readDouble(){
		return buffer.readDouble();
	}

	public String readUTF8(){

		int times=0;
		int utflen = buffer.readShort();
		if (utflen == -1) {
			return null;
		}
		byte[] bytearr = null;
		char[] chararr = null;

		bytearr = buffer.readBytes( utflen ).array();
		if(utflen > bytearr.length){
			return null;
		}
		chararr = new char[utflen];

		int c, char2, char3;
		int count = 0;
		int chararr_count = 0;

		while (count < utflen) {
			times++;
			if(times>1000){
				logger.error("读取UTF异常1...");
				return "sbsbsb";
			}
			c = (int) bytearr[count] & 0xff;
			if (c > 127) {
				break;
			}
			count++;
			chararr[chararr_count++] = (char) c;
		}
		times=0;
		while (count < utflen) {
			times++;
			if(times>1000){
				logger.error("读取UTF异常3...");
				return "sbsbsb";
			}
			c = (int) bytearr[count] & 0xff;
			switch (c >> 4) {
			case 0:
			case 1:
			case 2:
			case 3:
			case 4:
			case 5:
			case 6:
			case 7: /* 0xxxxxxx*/
			count++;
			chararr[chararr_count++] = (char) c;
			break;
			case 12:
			case 13: /* 110x xxxx   10xx xxxx*/
				count += 2;
				char2 = (int) bytearr[count - 1];
				chararr[chararr_count++] = (char) (((c & 0x1F) << 6) |
						(char2 & 0x3F));
				break;
			case 14: /* 1110 xxxx  10xx xxxx  10xx xxxx */
				count += 3;
				char2 = (int) bytearr[count - 2];
				char3 = (int) bytearr[count - 1];
				chararr[chararr_count++] = (char) (((c & 0x0F) << 12) |
						((char2 & 0x3F) << 6) |
						((char3 & 0x3F) << 0));
				break;
			default:
				logger.error("读取UTF异常2...");
				return "";
			}
		}
		return new String(chararr, 0, chararr_count);
	}


	public void writeBool( boolean value ){
		buffer.writeBoolean( value );
	}

	public void writeByte( byte value ){
		buffer.writeByte( value );
	}

	public void writeShort( short value ){
		buffer.writeShort( value );
	}

	public void writeInt( int value ){
		buffer.writeInt( value );
	}

	public void writeLong( long value ){
		buffer.writeLong( value );
	}

	public void writeFloat( float value ){
		buffer.writeFloat( value );
	}

	public void writeDouble( double value ){
		buffer.writeDouble( value );
	}

	public void writeUTF8( String value ){

		if( value == null){
			logger.error( "null string in ByteBuffer.writeUTF();");
			writeUTF8( "" );
			return;
		}
		byte[] bytes =  getByteArrFromUTF( value ) ;
		writeShort( (short)bytes.length );
		buffer.writeBytes( bytes );
	}
	
	

	public static byte[] getByteArrFromUTF(String str) {
		int strlen = str.length();
		int utflen = 0;
		int c, count = 0;

		/* use charAt instead of copying String to char array */
		for (int i = 0; i < strlen; i++) {
			c = str.charAt(i);
			if ((c >= 0x0001) && (c <= 0x007F)) {
				utflen++;
			} else if (c > 0x07FF) {
				utflen += 3;
			} else {
				utflen += 2;
			}
		}

		byte[] bytearr = new byte[utflen];
		int i = 0;
		for (i = 0; i < strlen; i++) {
			c = str.charAt(i);
			if (!((c >= 0x0001) && (c <= 0x007F))) {
				break;
			}
			bytearr[count++] = (byte) c;
		}

		for (; i < strlen; i++) {
			c = str.charAt(i);
			if ((c >= 0x0001) && (c <= 0x007F)) {
				bytearr[count++] = (byte) c;

			} else if (c > 0x07FF) {
				bytearr[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
				bytearr[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
				bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
			} else {
				bytearr[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
				bytearr[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
			}
		}
		return bytearr;
	}

}
